using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using MimeCloud.Foundations.ErrorLogging;

namespace MimeCloud.FTPUtil
{
    public static class QueryHelper
    {
        public static FtpStatusCode TryExecuteNonQuery(this FtpWebRequest ftpRequest)
        {
            try
            {
                return (ftpRequest.GetResponse() as FtpWebResponse).StatusCode;
            }
            catch (Exception ex)
            {
                ErrorHelper.LogError(new Exception("FTP Error on TryExecuteNonQuery, see inner exception",ex));
                return FtpStatusCode.CantOpenData;
            }
        }

        public static bool EnsurePathExists(ICredentials ftpCredentials, string fullPath)
        {
            string[] pathElements = fullPath.Replace("ftp://",String.Empty).Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
            //set up root path
            string curpath = String.Concat("ftp://",pathElements[0]);
            var ftpRequest = GetRequest(ftpCredentials, curpath);
            ftpRequest.Method = WebRequestMethods.Ftp.MakeDirectory;
            
            for (int i = 1; i < pathElements.Length; i++)
            {
                //add dir to path
                bool? exists = DoesPathElementExistAtPath(curpath, pathElements[i], ftpCredentials);
                curpath = String.Concat(curpath, "/", pathElements[i]);
                if (exists == null || exists.Value == false)
                {
                    //make dir
                    ftpRequest = GetRequest(ftpCredentials, curpath);
                    ftpRequest.Method = WebRequestMethods.Ftp.MakeDirectory;
                    ftpRequest.TryExecuteNonQuery();
                }
            }
            return true;
        }

        public static FtpWebRequest GetRequest(ICredentials ftpCredentials, string path)
        {
            var ftpRequest = WebRequest.Create(path) as FtpWebRequest;
            
            ftpRequest.KeepAlive = true;
            ftpRequest.Timeout = 100000;
            ftpRequest.Proxy = null;
            ftpRequest.ReadWriteTimeout = 100000;
                if (ftpCredentials != null)
                {
                    ftpRequest.Credentials = ftpCredentials;
                }
                else
                {
                    ftpRequest.UseDefaultCredentials = true;
                }

            return ftpRequest;
        }

        /// <summary>
        /// Determines the size of a file on an Ftp server
        /// </summary>
        /// <param name="fileUri">The path to the file of which to check the existence</param>
        /// <param name="ftpCredentials">The credentials to be used for user authetication</param>
        /// <returns>The length of the file in bytes if successful, otherwise null</returns>
        public static long? GetFileSize(string fileUri, ICredentials ftpCredentials)
        {
            long? result = -1;

            try
            {
                var ftpRequest = GetRequest(ftpCredentials,fileUri);
                ftpRequest.Method = WebRequestMethods.Ftp.GetFileSize;
               

                using (WebResponse response = ftpRequest.GetResponse())
                {
                    result = response.ContentLength;
                }
            }
            catch (Exception ex)
            {
                ErrorHelper.LogError(ex);
                result = null;
            }

            return result;
        }

        public static bool? DoesFileExist(string fileUri, ICredentials ftpCredentials)
        {
            long? size = GetFileSize(fileUri, ftpCredentials);
            if (size == null)
            {
                return false;
            }
            return size > -1 ? true : false;
        }
        
        public static bool? DoesPathElementExistAtPath(string fileUri, string pathElement, ICredentials ftpCredentials)
        {
            var ftpRequest = WebRequest.Create(fileUri) as FtpWebRequest;
            ftpRequest.Credentials = ftpCredentials;
            ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory;
            ftpRequest.Proxy = null;

            try
            {
                using (StreamReader sr = new StreamReader(ftpRequest.GetResponse().GetResponseStream()))
                {
                    string line = sr.ReadLine();
                    while (line != null)
                    {
                        if (line.ToLower().Trim() == pathElement.ToLower().Trim())
                        {
                            sr.BaseStream.Close();
                            return true;
                        }
                        line = sr.ReadLine();
                    }
                    sr.BaseStream.Close();
                }
                return false;
            }
            catch
            {
                return null;
            }
        }
    }
}
